package cn.baage.campus.config.security.filer;

import cn.baage.campus.config.security.BaseUserDetail;
import cn.baage.campus.constant.BaageConstant;
import cn.baage.campus.constant.CacheConstant;
import cn.baage.campus.model.dto.LoginUser;
import cn.baage.campus.service.RedisService;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/**
 * @Description: 自定义token认证过滤器
 * @Author: 八阿哥
 * @url: baage.cn
 * @Version: 1.0
 **/
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class RestAuthenticationTokenFilter extends OncePerRequestFilter {

    private final RedisService<LoginUser> redisService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 1. 获取token
        String token = request.getHeader(BaageConstant.AUTH_HEADER);
        if (StrUtil.isBlank(token)) {
            filterChain.doFilter(request, response);
            return;
        }
        String code;
        String userId;
        try {
            String[] split = token.split(BaageConstant.TOKEN_SPLIT);
            code = split[0];
            userId = split[1];
        } catch (Exception e) {
            logger.debug("非法Token");
            filterChain.doFilter(request, response);
            return;
        }
        // 2. 从缓存中获取用户信息
        String cacheTokenKey = CacheConstant.AUTH_KEY + userId + ":" + code;
        if (!redisService.hasKey(cacheTokenKey)) {
            logger.debug("Token无效或已失效");
            filterChain.doFilter(request, response);
            return;
        }
        String cacheInfoKey = CacheConstant.AUTH_KEY + userId + ":info" + userId;
        LoginUser loginUser = redisService.get(cacheInfoKey);
        // 3. 存入 SecurityContext
        BaseUserDetail baseUserDetail = new BaseUserDetail();
        baseUserDetail.setCode(code);
        baseUserDetail.setLoginUser(loginUser);
        UsernamePasswordAuthenticationToken authenticationToken
                = new UsernamePasswordAuthenticationToken(baseUserDetail, null, baseUserDetail.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        filterChain.doFilter(request,response);
    }

}
